package de.herberlin.server.ui;

import java.util.*;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;

import javax.swing.table.AbstractTableModel;

/**
 * Model for diplaying Preferences in a JTable.
 * The model is used with Bremsserver configuration dialog
 * 
 * @author hans joachim herbertz
 * created 21.02.2004
 */
class PreferenceTableModel extends AbstractTableModel {

	/**
	 * Preferences as given from the application.
	 */
	private Preferences prefs = null;
	/**
	 * Holds Preferences in an alphabetic order.
	 */
	private List list = new ArrayList();
	/**
	 * Stores if Preferences were modified.
	 */
	private boolean updateFlag = false;
	/**
	 * Table headlines.
	 */
	private String[] headlines={"Key","Value"};

	/**
	 * Constructor reads and sorts preferences.
	 */
	public PreferenceTableModel(Preferences prefs)
		throws BackingStoreException {
		super();
		this.prefs = prefs;
		if (prefs == null) {
			throw new RuntimeException("Preferences may not be null.");
		}
		String[] keys = prefs.keys();
		for (int i = 0; i < keys.length; i++) {
			list.add(new Property(keys[i], prefs.get(keys[i], "")));
		}
		Collections.sort(list);
	}
	
	/**
	 * Deletes the selected row.
	 * @param rowIndex
	 */
	public void deleteRow(int rowIndex) {
		list.remove(rowIndex);
		fireTableRowsDeleted(rowIndex, rowIndex);
	}

	/**
	 * Writes the properties in the list back to
	 * the Preferences.
	 * @throws BackingStoreException
	 */
	public void store() throws BackingStoreException {
		if (updateFlag) {

			String[] keys = prefs.keys();
			for (int i = 0; i < keys.length; i++) {
				prefs.remove(keys[i]);
			}
			Iterator it = list.iterator();
			while (it.hasNext()) {
				Property prop = (Property) it.next();
				if (prop.key.length() > 0) {
					prefs.put(prop.key, prop.value);
				}
			}
		}
	}
	/**
	 * Sets table headlines.
	 * @param headlines
	 */
	public void setHeadlines(String[] headlines){
		if (headlines.length==getColumnCount()){
			this.headlines=headlines;
			fireTableStructureChanged();
		} else {
			throw new RuntimeException("Bad length of headlines: "+headlines.length);
		}
	}
	
	/**
	 * Adds an empty row at the beginning of the table
	 */
	public void addRow() {
		list.add(0, new Property("", ""));
		fireTableRowsInserted(list.size(), list.size());
	}
	/**
	 * @see javax.swing.table.TableModel#getColumnCount()
	 */
	public int getColumnCount() {
		return 2;
	}

	/**
	 * @see javax.swing.table.TableModel#getRowCount()
	 */
	public int getRowCount() {
		return list.size();
	}

	/**
	 * @see javax.swing.table.TableModel#getValueAt(int, int)
	 */
	public Object getValueAt(int rowIndex, int columnIndex) {
		Property prop = (Property) list.get(rowIndex);
		switch (columnIndex) {
			case 0 :
				return prop.key;
			case 1 :
				return prop.value;
			default :
				return null;
		}
	}

	/**
	 * Simple data structure for internal use.
	 * Holds Preferences.
	 */
	private class Property implements Comparable {
		String key = null;
		String value = null;

		Property(String key, String value) {
			this.key = key;
			this.value = value;
		}
		/**
		 * @see java.lang.Comparable#compareTo(java.lang.Object)
		 */
		public int compareTo(Object o) {

			if (o != null && o instanceof Property) {
				return this.key.compareToIgnoreCase(((Property) o).key);
			}
			return 0;
		}

	}//~ Property.class
	
	/**
	 * @see javax.swing.table.TableModel#getColumnName(int)
	 */
	public String getColumnName(int column) {
		switch (column) {
			case 0 :
				return headlines[0];
			case 1 :
				return headlines[1];
			default :
				return "";
		}
	}

	/**
	 * @see javax.swing.table.TableModel#isCellEditable(int, int)
	 */
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		return true;
	}

	/**
	 * @see javax.swing.table.TableModel#setValueAt(java.lang.Object, int, int)
	 */
	public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
		Property prop = (Property) list.get(rowIndex);
		updateFlag = true;
		switch (columnIndex) {
			case 0 :
				prop.key = "" + aValue;
				return;
			case 1 :
				prop.value = "" + aValue;
				return;
			default :
				return;
		}
	}

}
